import inet.examples.ethernet.lans.ethernetline;
import inet.linklayer.ethernet.EtherBus;
import inet.linklayer.ppp.PPPInterfaceWithDLThruputMeter;
import inet.linklayer.ppp.ThruputMeter;
import inet.nodes.inet.StandardHostWithDLThruputMeter;
import inet.world.ChannelControl;
import inet.nodes.inet.Router;
import inet.nodes.wireless.WirelessAPWithEthSimplified;
import inet.nodes.wireless.WirelessAPSimplified;
import inet.nodes.wireless.WirelessHostSimplified;
import inet.nodes.ethernet.EtherSwitch;
import inet.nodes.wireless.WirelessAPWithEth;
import inet.networklayer.autorouting.FlatNetworkConfigurator;
import ned.DatarateChannel;
import inet.nodes.inet.StandardHost;
import inet.nodes.wireless.WirelessHost;
import ned.DatarateChannel;
import inet.applications.udpapp.UDPBasicApp;


network Network2AP
{
    parameters:
        int numOfHttpClients = default(0);
        int numOfVoipClients = default(0);
        int numOfFtpDownloadClients = default(0);
        int numOfFtpUploadClients = default(0);

        int ISPDatarate @unit(Gbps) = default(10Gbps);
        int DSLDatarate @unit(Mbps);
        int FTPDatarate @unit(Gbps) = default(10Gbps);
        int VoIPDatarate @unit(Gbps) = default(10Gbps);

        @display("bgb=967,476;bgl=9");
    types:
        channel FTPConnection extends DatarateChannel
        {
            delay = 45ms;
            datarate = FTPDatarate;
        }
        channel VoIPConnection extends DatarateChannel
        {
            delay = 5ms;
            datarate = VoIPDatarate;
        }
        channel ISPConnection extends DatarateChannel
        {
            delay = 10ms;
            datarate = ISPDatarate;
        }

        channel DSLConnection extends DatarateChannel
        {
            delay = 15ms;
            datarate = DSLDatarate;
        }

    submodules:
        voipServer: StandardHost {
            numUdpApps = numOfVoipClients;
            udpAppType = "VoIPApp";
            udpApp[*].messageFreq = 0.02s; // 50 packets per Second
            udpApp[*].messageLength = 48B; // 16 virtual byte rtp header + 32 byte voip
            @display("i=misc/globe;p=600,59");
        }
        //sends data to clients
        FTPServer1: StandardHost {
            numTcpApps = numOfFtpDownloadClients;
            tcpAppType = "TCPSessionApp";
            @display("i=misc/globe;p=489,25");
        }
        //receives data from ftp clients
        FTPServer2: StandardHost {
            numTcpApps = 1;
            tcpAppType = "TCPSinkApp";
            @display("i=misc/globe;p=489,265");
        }
        HttpServer: StandardHost {
            @display("i=misc/globe;p=614,228");
        }
		//Voice over IP users. They need a minimum Quality of Service
        voipHost[numOfVoipClients]: WirelessHostSimplified {
            numUdpApps = 1;
            udpAppType = "VoIPApp";
            udpApp[*].messageFreq = 0.02s;
            udpApp[*].messageLength = 48B; // 16 virtual byte rtp header + 32 byte voip
            @display("is=s;i=device/cellphone2");
        }
        //ftp users eighter uploading or downloading large files all the time
        ftpDownHost[numOfFtpDownloadClients]: WirelessHostSimplified {
            numTcpApps = 1;
            tcpAppType = "TCPSinkApp";
            @display("is=s;i=device/disk");
        }
        ftpUpHost[numOfFtpUploadClients]: WirelessHostSimplified {
            numTcpApps = 1;
            tcpAppType = "TCPSessionApp";
            @display("is=s;i=device/disk");
        }
        //http webbrowsing clients
        httpHost[numOfHttpClients]: WirelessHostSimplified {
            @display("is=s;i=device/wifilaptop");
        }

        channelControl: ChannelControl;
        flatNetworkConfigurator: FlatNetworkConfigurator;
        accessPoint: WirelessAPWithEthSimplified {
            @display("p=55,84");
        }
        DSLRouter: Router {
            routingFile = "RT_DSLRouter.mrt";
            @display("p=183,128");
        }
        ISPRouter: Router {
            routingFile = "RT_ISPRouter.mrt";
            @display("p=362,120");
        }
        router: Router {
            routingFile = "RT_Router.mrt";
            @display("p=489,120");
        }

        dslDownThruputMeter: ThruputMeter {
            @display("p=271,139");
        }
        dslUpThruputMeter: ThruputMeter {
            @display("p=271,111");
        }
        httpDownThruputMeter: ThruputMeter {
            @display("p=540,194");
        }
        httpUpThruputMeter: ThruputMeter {
            @display("p=570,158");
        }
        voipDownThruputMeter: ThruputMeter {
            @display("p=555,85");
        }
        voipUpThruputMeter: ThruputMeter {
            @display("p=574,100");
        }
        ftpDownThruputMeter: ThruputMeter {
            @display("p=462,71");
        }
        ftpUpThruputMeter: ThruputMeter {
            @display("p=477,194");
        }
        etherSwitch: EtherSwitch {
            @display("p=125,127");
            mac.fullduplex = true; // enable duplex mode
            mac.txRate = 100Mbps;
        }
        accessPoint1: WirelessAPWithEthSimplified {
            @display("p=55,146");
        }
    connections:

        ISPRouter.pppg++ <--> ISPConnection <--> router.pppg++;

        voipServer.pppg$o++ --> VoIPConnection --> voipDownThruputMeter.in;
        voipDownThruputMeter.out --> router.pppg$i++;
        voipUpThruputMeter.in <-- VoIPConnection <-- router.pppg$o++;
        voipServer.pppg$i++ <-- voipUpThruputMeter.out;

        FTPServer1.pppg$o++ --> FTPConnection --> ftpDownThruputMeter.in;
        ftpDownThruputMeter.out --> router.pppg$i++;
        FTPServer1.pppg$i++ <-- FTPConnection <-- router.pppg$o++;

        FTPServer2.pppg$i++ <-- ftpUpThruputMeter.out;
        ftpUpThruputMeter.in <-- FTPConnection <-- router.pppg$o++;
        FTPServer2.pppg$o++ --> FTPConnection --> router.pppg$i++;

        HttpServer.pppg$o++ --> FTPConnection --> httpDownThruputMeter.in;
        httpDownThruputMeter.out --> router.pppg$i++;
        httpUpThruputMeter.in <-- FTPConnection <-- router.pppg$o++;
        HttpServer.pppg$i++ <-- httpUpThruputMeter.out;

        ISPRouter.pppg$i++ <-- dslUpThruputMeter.out;
        dslUpThruputMeter.in <-- DSLConnection <-- DSLRouter.pppg$o++;
        ISPRouter.pppg$o++ --> DSLConnection --> dslDownThruputMeter.in;
        dslDownThruputMeter.out --> DSLRouter.pppg$i++;

        DSLRouter.ethg++ <--> etherSwitch.ethg++;
        accessPoint.ethg++ <--> etherSwitch.ethg++;
        etherSwitch.ethg++ <--> accessPoint1.ethg++;
}
